#include "Task4.cpp"
#include <sys/wait.h>
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <string>
#include<vector>
#define PROCESS_COUNT 10
using namespace std;
vector<task_t>tasks;
class channel//先描述
{
    public:
    channel(int wfd,pid_t processid,const string&s):_wfd(wfd),_processid(processid),_processname(s)
    {

    }
    public:
    int _wfd;//将来父进程通过这个fd向子进程写入
    pid_t _processid;//子进程id
    string _processname;//子进程名字
};
void slaver()
{
    int taskcode=0;
    while(true)//不停读
    {
   ssize_t n=read(0,&taskcode,sizeof(int));
   if(n==0)
   {
    //读到文件末尾（写端关闭）
    cout<< "write close"<<endl;
    break;
   }
   else if(n>0){
    //读到了，执行任务
    taskcode-=1;
    if(taskcode>=0&&taskcode<tasks.size())
    tasks[taskcode]();
   }
   else
   break;//读取失败
    }
}
int Initpool(vector<channel>*channels)//输出型参数，往vector里存放
{
    vector<int> oldfd;
    
    for(int i=0;i<PROCESS_COUNT;i++)
    {
        //创建子进程前先创建管道
    int pipefd[2]={0};
    int n=pipe(pipefd);
    if(n==-1){perror("pipe");return -1;}
        pid_t id=fork();
        if(id<0)
        {
            perror("fork");
            return -2;
        }
        else if(id==0)
        {
            //关闭继承父的写通道
            for(auto e:oldfd)
            {
                close(e);
                cout<<e<<" ";
            }
            cout<<endl;
            //child 父写子读，子关闭写通道
            close(pipefd[1]);
            //让子没有管道概念
            dup2(pipefd[0],0);//往后往0读就行，把标准输入重定向为管道读端
            close(pipefd[0]);
            //获取任务码，执行任务
            slaver();
            exit(0);

        }
        else
        {
            //farther
            close(pipefd[0]);
            //写入字段
            string processname="process "+to_string(i);
            channels->push_back(channel(pipefd[1],id,processname));
            //记录历史打开的写fd
            oldfd.push_back(pipefd[1]);
        }
    }
}
void Control(const vector<channel>&channels)
{
      int which=0;
    while(true)
    {
    //选择任务(让用户选择)
    int select=0;
    cin>>select;
    if(select<=0||select>4)
    {
        cout<<"select err"<<endl;
        break;
    }
    //选择进程
    
    //发送任务
    write(channels[which]._wfd,&select,sizeof(int));
    which++;
    which%=channels.size();
    }
}
void QuitProcess(const vector<channel>&channels)
{
    for(int i=0;i<channels.size();i++)
    {
        close(channels[i]._wfd);
        waitpid(channels[i]._processid,nullptr,0);//等待子进程
    }
}
int main()
{
    //加载任务
    loadtask(&tasks);
    //再组织
    vector<channel> channels;
    //初始化
    Initpool(&channels);
    //控制进程
    Control(channels);
    //清理工作
    QuitProcess(channels);
    return 0;
}